/*
 * Created on 2008-3-7
 *
 * TODO
 */
package jacky.lanlan.song.extension.struts.interceptor;

import jacky.lanlan.song.extension.struts.InfrastructureKeys;
import jacky.lanlan.song.extension.struts.scope.FlashScopeContainer;
import jacky.lanlan.song.web.Scope;

import java.util.Enumeration;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.struts.action.ActionForward;

/**
 * 实现 Flash 范围语意的拦截器。优先级100。
 * <p>
 * 客户端不需要使用这个拦截器。
 * 
 * @see jacky.lanlan.song.web.Scope
 * @author Jacky.Song
 */
@SuppressWarnings("unused")
public class FlashScopeSetter extends ActionInterceptorAdapter {

	@SuppressWarnings("unchecked")
	@Override
	public String preHandle(HttpServletRequest request,
			HttpServletResponse response, Object action) throws Exception {
		// Action执行前设置好FlashScopeValue
		HttpSession session = request.getSession(false);
		if(session!=null) {
			for (Enumeration e = session.getAttributeNames() ; e.hasMoreElements() ;) {
				String name = (String) e.nextElement();
				if (name.startsWith(Scope.Flash + "_")) {// 所有的FlashScopeValue都有(Scope.Flash+"_")前缀
					FlashScopeContainer scope = (FlashScopeContainer) session.getAttribute(name);
					// 如果 FlashScopeContainer 还没有被销毁，就倒数
					if(scope!=null) {
						scope.refreshRequest(request);
						scope.countdown();
					}
				}
			}
		}
		return null;
	}
	
	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object action, ActionForward distination) throws Exception {
		this.preHandle(request, response, action);
		// Action执行后再设置一次FlashScopeValue
	}
	
	/*
	 * 上面用前后两个拦截方法，就实现了 Flash 范围的语意。
	 * 
	 * 假设A为Action，P为页面，F为Flash值，流程如下：
	 * 
	 * 在A1中创建F -> FlashScopeSetter.postHandle()调用F的countdown()1次 -> 导航到P1，P1可以得到F (无论是否是Redirect) ->
	 * 
	 * 同一客户端的新请求 -> FlashScopeSetter.preHandle()调用F的countdown()1次 -> 请求到达A2，A2可以得到F ->
	 * 
	 * FlashScopeSetter.postHandle()调用F的countdown()1次(F自动销毁) -> 导航到P2，P2不能再得到F
	 * 
	 */
	
	public int priority() {
		return 100;// 优先级在默认拦截器中最高，这样才可以保证所有的后续操作都可以访问到FlashScopeValue
	}
	
}
